package com.laomou.logdog.controller;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Objects;
import java.util.Properties;

public class OptionController {
    @FXML
    ComboBox<String> m_comboDeviceCmd;
    @FXML
    ComboBox<String> m_comboDeviceName;
    @FXML
    private TextField m_tfFindWord;
    @FXML
    private TextField m_tfRemoveWord;
    @FXML
    private TextField m_tfShowPid;
    @FXML
    private TextField m_tfShowTid;
    @FXML
    private TextField m_tfShowTag;
    @FXML
    private TextField m_tfRemoveTag;
    @FXML
    private TextField m_tfHighlight;
    @FXML
    private CheckBox m_chkEnableFind;
    @FXML
    private CheckBox m_chkEnableRemove;
    @FXML
    private CheckBox m_chkEnableShowPid;
    @FXML
    private CheckBox m_chkEnableShowTid;
    @FXML
    private CheckBox m_chkEnableShowTag;
    @FXML
    private CheckBox m_chkEnableRemoveTag;
    @FXML
    private CheckBox m_chkEnableHighlight;
    @FXML
    private CheckBox m_chkVerbose;
    @FXML
    private CheckBox m_chkDebug;
    @FXML
    private CheckBox m_chkInfo;
    @FXML
    private CheckBox m_chkWarn;
    @FXML
    private CheckBox m_chkError;
    @FXML
    private CheckBox m_chkFatal;

    @FXML
    private CheckBox m_chkLine;
    @FXML
    private CheckBox m_chkDate;
    @FXML
    private CheckBox m_chkTime;
    @FXML
    private CheckBox m_chkLogLv;
    @FXML
    private CheckBox m_chkPid;
    @FXML
    private CheckBox m_chkTid;
    @FXML
    private CheckBox m_chkTag;
    @FXML
    private CheckBox m_chkMsg;

    @FXML
    private CheckBox m_chkRunE;
    @FXML
    private CheckBox m_chkAnrE;

    @FXML
    private TextField m_tfGotoLine;
    @FXML
    private TextField m_tfFontSize;
    @FXML
    private Button m_btnDevice;
    @FXML
    private Button m_btnClear;
    @FXML
    private Button m_btnRun;
    @FXML
    private ToggleButton m_tbtnPause;
    @FXML
    private Button m_btnStop;

    private MainController mainController;

    private String mStrFindWord = "";
    private String mStrRemoveWord = "";
    private String mStrPid = "";
    private String mStrTid = "";
    private String mStrFindTag = "";
    private String mStrRemoveTag = "";
    private String mStrHighlight = "";

    public void setMainconreoller(MainController conreoller) {
        this.mainController = conreoller;
    }

    public void initialize() {
        m_chkVerbose.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setLogLV(MainController.LOG_LV_VERBOSE, newValue);
        });
        m_chkDebug.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setLogLV(MainController.LOG_LV_DEBUG, newValue);
        });
        m_chkInfo.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setLogLV(MainController.LOG_LV_INFO, newValue);
        });
        m_chkWarn.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setLogLV(MainController.LOG_LV_WARN, newValue);
        });
        m_chkError.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setLogLV(MainController.LOG_LV_ERROR, newValue);
        });
        m_chkFatal.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setLogLV(MainController.LOG_LV_FATAL, newValue);
        });

        m_chkLine.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setTableColumn(MainController.TABLE_COLUMN_LINE, newValue);
        });
        m_chkDate.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setTableColumn(MainController.TABLE_COLUMN_DATE, newValue);
        });
        m_chkTime.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setTableColumn(MainController.TABLE_COLUMN_TIME, newValue);
        });
        m_chkLogLv.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setTableColumn(MainController.TABLE_COLUMN_LEVEL, newValue);
        });
        m_chkPid.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setTableColumn(MainController.TABLE_COLUMN_PID, newValue);
        });
        m_chkTid.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setTableColumn(MainController.TABLE_COLUMN_TID, newValue);
        });
        m_chkTag.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setTableColumn(MainController.TABLE_COLUMN_TAG, newValue);
        });
        m_chkMsg.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setTableColumn(MainController.TABLE_COLUMN_MESSAGE, newValue);
        });
        m_chkRunE.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setExceptionFilter(MainController.EXCEPTION_RUNE, newValue);
            updateExceptionChk();
        });
        m_chkAnrE.selectedProperty().addListener((observable, oldValue, newValue) -> {
            mainController.setExceptionFilter(MainController.EXCEPTION_ANR, newValue);
            updateExceptionChk();
        });

        ObservableList<String> device =
                FXCollections.observableArrayList(
                        "Android"
                );
        m_comboDeviceName.setItems(device);
        m_comboDeviceName.getSelectionModel().select(0);

        ObservableList<String> cmd =
                FXCollections.observableArrayList(
                        "logcat -v threadtime",
                        "logcat -v time"
                );
        m_comboDeviceCmd.setItems(cmd);
        m_comboDeviceCmd.getSelectionModel().select(0);

        m_chkEnableFind.selectedProperty().addListener((observable, oldValue, newValue) -> {
            useFilter(m_chkEnableFind);
        });
        m_chkEnableRemove.selectedProperty().addListener((observable, oldValue, newValue) -> {
            useFilter(m_chkEnableRemove);
        });
        m_chkEnableShowPid.selectedProperty().addListener((observable, oldValue, newValue) -> {
            useFilter(m_chkEnableShowPid);
        });
        m_chkEnableShowTid.selectedProperty().addListener((observable, oldValue, newValue) -> {
            useFilter(m_chkEnableShowTid);
        });
        m_chkEnableShowTag.selectedProperty().addListener((observable, oldValue, newValue) -> {
            useFilter(m_chkEnableShowTag);
        });
        m_chkEnableRemoveTag.selectedProperty().addListener((observable, oldValue, newValue) -> {
            useFilter(m_chkEnableRemoveTag);
        });
        m_tfFindWord.textProperty().addListener(((observable, oldValue, newValue) -> {
            tagFilter(m_tfFindWord);
        }));
        m_tfRemoveWord.textProperty().addListener(((observable, oldValue, newValue) -> {
            tagFilter(m_tfRemoveWord);
        }));
        m_tfShowPid.textProperty().addListener(((observable, oldValue, newValue) -> {
            tagFilter(m_tfShowPid);
        }));
        m_tfShowTid.textProperty().addListener(((observable, oldValue, newValue) -> {
            tagFilter(m_tfShowTid);
        }));
        m_tfShowTag.textProperty().addListener(((observable, oldValue, newValue) -> {
            tagFilter(m_tfShowTag);
        }));
        m_tfRemoveTag.textProperty().addListener(((observable, oldValue, newValue) -> {
            tagFilter(m_tfRemoveTag);
        }));
        m_tfHighlight.textProperty().addListener((observable, oldValue, newValue) -> {
            tagFilter(m_tfHighlight);
        });

        m_tfGotoLine.addEventHandler(KeyEvent.KEY_TYPED, event -> {
            if (event.getCharacter().matches("[0-9]")) {
            } else {
                event.consume();
            }
        });
        m_tfGotoLine.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
            if (event.getCode() == KeyCode.ENTER) {
                if (m_tfGotoLine.getText().isEmpty()) {
                    return;
                }
                int line = Integer.valueOf(m_tfGotoLine.getText());
                mainController.gotoLine(line);
            }
        });
        m_tfFontSize.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
            if (event.getCode() == KeyCode.ENTER) {
                if (m_tfFontSize.getText().length() == 0) {
                    return;
                }
                int line = Integer.valueOf(m_tfFontSize.getText());
                mainController.setFontSize(line);
            }
        });
    }

    public void loadFilter() {
        try {
            Properties p = new Properties();
            p.load(new FileInputStream(".filter"));
            m_tfFindWord.setText(p.getProperty("FIND_WORD"));
            m_tfRemoveWord.setText(p.getProperty("REMOVE_WORD"));
            m_tfShowTag.setText(p.getProperty("SHOW_TAG"));
            m_tfRemoveTag.setText(p.getProperty("REMOVE_TAG"));
            m_tfShowPid.setText(p.getProperty("SHOW_PID"));
            m_tfShowTid.setText(p.getProperty("SHOW_TID"));
            m_tfHighlight.setText(p.getProperty("HIGHLIGHT"));
        } catch (Exception e) {
            // e.printStackTrace();
            System.err.println("loadFilter exception");
        }
    }

    public void saveFilter() {
        try {
            Properties p = new Properties();
            p.setProperty("FIND_WORD", m_tfFindWord.getText());
            p.setProperty("REMOVE_WORD", m_tfRemoveWord.getText());
            p.setProperty("SHOW_TAG", m_tfShowTag.getText());
            p.setProperty("REMOVE_TAG", m_tfRemoveTag.getText());
            p.setProperty("SHOW_PID", m_tfShowPid.getText());
            p.setProperty("SHOW_TID", m_tfShowTid.getText());
            p.setProperty("HIGHLIGHT", m_tfHighlight.getText());
            p.store(new FileOutputStream(".filter"), "LogDog filter file");
        } catch (Exception e) {
            // e.printStackTrace();
            System.err.println("saveFilter exception");
        }
    }

    @FXML
    public void onUpdateDevice() {
        mainController.updateDeviceList();
    }

    @FXML
    public void onStop() {
        mainController.stopProcess();
        setProcessBtn(false);
    }

    @FXML
    public void onResumeOrPause() {
        mainController.pauseProcess();
    }

    @FXML
    public void onClear() {
        mainController.clearData();
        mainController.updateTable();
    }

    @FXML
    public void onRun() {
        mainController.startProcess();
        setProcessBtn(true);
    }

    public void setProcessBtn(boolean bStart) {
        if (!bStart) {
            m_btnRun.setDisable(false);
            m_btnStop.setDisable(true);
            m_btnClear.setDisable(true);
            m_tbtnPause.setDisable(true);
        } else {
            m_btnRun.setDisable(true);
            m_btnStop.setDisable(false);
            m_btnClear.setDisable(false);
            m_tbtnPause.setDisable(false);
            m_tbtnPause.setSelected(false);
            m_tbtnPause.setText("Pause");
        }
    }

    private void updateExceptionChk() {
        if (mainController.enableExceptionFilter()) {
            m_chkVerbose.setDisable(true);
            m_chkDebug.setDisable(true);
            m_chkInfo.setDisable(true);
            m_chkWarn.setDisable(true);
            m_chkError.setDisable(true);
            m_chkFatal.setDisable(true);
        } else {
            m_chkVerbose.setDisable(false);
            m_chkDebug.setDisable(false);
            m_chkInfo.setDisable(false);
            m_chkWarn.setDisable(false);
            m_chkError.setDisable(false);
            m_chkFatal.setDisable(false);
        }
    }

    public void setPauseText(String text, boolean check) {
        m_tbtnPause.setSelected(check);
        m_tbtnPause.setText(text);
    }

    public void setGotoLineText(String text) {
        m_tfGotoLine.setText(text);
    }

    public void setDeviceList(ObservableList<String> list) {
        if (!list.isEmpty()) {
            m_comboDeviceName.setItems(list);
            m_comboDeviceName.getSelectionModel().select(0);
        }
    }

    public String getDeviceName() {
        if (m_comboDeviceName.getSelectionModel().getSelectedItem().equals("Android")) {
            return "";
        }
        return m_comboDeviceName.getSelectionModel().getSelectedItem();
    }

    public String getDeviceCmd() {
        return m_comboDeviceCmd.getSelectionModel().getSelectedItem();
    }

    private void tagFilter(TextField textField) {
        boolean textChanged = false;
        if (textField.equals(m_tfFindWord) && m_chkEnableFind.isSelected()) {
            setWordFind(m_tfFindWord.getText());
            textChanged = true;
        }
        if (textField.equals(m_tfRemoveWord) && m_chkEnableRemove.isSelected()) {
            setWordRemove(m_tfRemoveWord.getText());
            textChanged = true;
        }
        if (textField.equals(m_tfShowPid) && m_chkEnableShowPid.isSelected()) {
            setPid(m_tfShowPid.getText());
            textChanged = true;
        }
        if (textField.equals(m_tfShowTid) && m_chkEnableShowTid.isSelected()) {
            setTid(m_tfShowTid.getText());
            textChanged = true;
        }
        if (textField.equals(m_tfShowTag) && m_chkEnableShowTag.isSelected()) {
            setTagFind(m_tfShowTag.getText());
            textChanged = true;
        }
        if (textField.equals(m_tfRemoveTag) && m_chkEnableRemoveTag.isSelected()) {
            setTagRemove(m_tfRemoveTag.getText());
            textChanged = true;
        }
        if (textChanged) {
            mainController.setChangedFilter(MainController.STATUS_CHANGE);
            mainController.runFilter();
        }
    }

    private void useFilter(CheckBox checkBox) {
        if (checkBox.equals(m_chkEnableFind)) {
            setWordFind(checkBox.isSelected() ? m_tfFindWord.getText() : "");
        }
        if (checkBox.equals(m_chkEnableRemove)) {
            setWordRemove(checkBox.isSelected() ? m_tfRemoveWord.getText() : "");
        }
        if (checkBox.equals(m_chkEnableShowPid)) {
            setPid(checkBox.isSelected() ? m_tfShowPid.getText() : "");
        }
        if (checkBox.equals(m_chkEnableShowTid)) {
            setTid(checkBox.isSelected() ? m_tfShowTid.getText() : "");
        }
        if (checkBox.equals(m_chkEnableShowTag)) {
            setTagFind(checkBox.isSelected() ? m_tfShowTag.getText() : "");
        }
        if (checkBox.equals(m_chkEnableRemoveTag)) {
            setTagRemove(checkBox.isSelected() ? m_tfRemoveTag.getText() : "");
        }
        mainController.setChangedFilter(MainController.STATUS_CHANGE);
        mainController.runFilter();
    }

    private void setWordFind(String wordFind) {
        this.mStrFindWord = wordFind;
    }

    private void setWordRemove(String wordRemove) {
        this.mStrRemoveWord = wordRemove;
    }

    private void setTagFind(String tagFind) {
        this.mStrFindTag = tagFind;
    }

    private void setTagRemove(String tagRemove) {
        this.mStrRemoveTag = tagRemove;
    }

    public String getFindWord() {
        return mStrFindWord;
    }

    public String getRemoveWord() {
        return mStrRemoveWord;
    }

    public String getPid() {
        return mStrPid;
    }

    private void setPid(String pid) {
        this.mStrPid = pid;
    }

    public String getTid() {
        return mStrTid;
    }

    private void setTid(String tid) {
        this.mStrTid = tid;
    }

    public String getFindTag() {
        return mStrFindTag;
    }

    public String getRemoveTag() {
        return mStrRemoveTag;
    }

    public String getHighlight() {
        return mStrHighlight;
    }

    private void setHighlight(String highlight) {
        this.mStrHighlight = highlight;
    }

    public boolean enableFindWord() {
        return m_chkEnableFind.isSelected();
    }

    public boolean enableRemoveWord() {
        return m_chkEnableRemove.isSelected();
    }

    public boolean enablePid() {
        return m_chkEnableShowPid.isSelected();
    }

    public boolean enableTid() {
        return m_chkEnableShowTid.isSelected();
    }

    public boolean enableTagShow() {
        return m_chkEnableShowTag.isSelected();
    }

    public boolean enableTagRemove() {
        return m_chkEnableRemoveTag.isSelected();
    }

    public boolean enableHighlight() {
        return m_chkEnableHighlight.isSelected();
    }

    public boolean enablePause() {
        return m_tbtnPause.isSelected();
    }
}
